﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Mbs.Collections;

namespace Mbs.Messaging.Imp
{
    public class Subject<TMessage> :MarshalByRefObject, ISubject<TMessage>, IDisposable
    {
        
        public Subject() : this(typeof(TMessage).Name) { }
        public Subject(string name)
        {
            Debug.Assert(!string.IsNullOrEmpty(name));
            Name = name;
        }

        public string Name { get; set; }
        public ISubscriber<TMessage> Subscriber { get; set; }
        public IExecutor<TMessage> Executor { get; set; }
        public bool Closed { get; private set; }
        public IQueue<KeyValuePair<object, TMessage>> Queue { get; set; }


        public event ObserverHandler<TMessage> Observers
        {
            add
            {
                Subscriber.Subscribe(value);
            }
            remove
            {
                Subscriber.Unsubscribe(value);
            }
        }

        public event PreFilterHandler<TMessage> PreFilters
        {
            add
            {
                Subscriber.SubscribePreFilter(value);
            }
            remove
            {
                Subscriber.UnsubscribePreFilter(value);
            }
        }


        public event FilterHandler<TMessage> Filters
        {
            add
            {
                Subscriber.SubscribeFilter(value);
            }
            remove
            {
                Subscriber.UnsubscribeFilter(value);
            }
        }


        public void Close()
        {
            Closed = true;
            Queue.Dispose();
            Subscriber.ClearAll();
        }

        public void Publish(object sender, TMessage message)
        {
            if (Closed) return;

            var pair = new KeyValuePair<object, TMessage>(sender, message);
            Queue.Enqueue(pair);

            Executor.Execute();
        }

        void IPublisher.Publish(object sender, object message)
        {
            Publish(sender, (TMessage)message);
        }

        public void Dispose()
        {
            Close();
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }
       
    }
  
}
